package com.ruoyi.common.utils.bean;

import com.ruoyi.common.annotation.ForUpdate;
import com.ruoyi.common.utils.DateUtils;
import io.netty.util.internal.ObjectUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.Workbook;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Bean 工具类
 *
 * @author ruoyi
 */
public class BeanUtils extends org.springframework.beans.BeanUtils
{
    /** Bean方法名中属性名开始的下标 */
    private static final int BEAN_METHOD_PROP_INDEX = 3;

    /** * 匹配getter方法的正则表达式 */
    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");

    /** * 匹配setter方法的正则表达式 */
    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");

    /**
     * Bean属性复制工具方法。
     *
     * @param dest 目标对象
     * @param src 源对象
     */
    public static void copyBeanProp(Object dest, Object src)
    {
        try
        {
            copyProperties(src, dest);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


    /**
     * 将Object转换成List类型
     *
     * @param obj   Object对象
     * @param clazz 数据类型
     * @param <T>   泛型类型
     * @return 转换结果
     */
    public static <T> List<T> castList(Object obj, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        // 如果不是List<?>对象，是没有办法转换的
        if (obj instanceof List<?>) {
            for (Object o : (List<?>) obj) {
                // 根据业务需要来决定这里要不要将null值还原放进去
                if (o == null) {
                    result.add(clazz.cast(null));
                    continue;
                }
                // 转换前的前置判断，避免clazz.cast的时候出现类转换异常
                if (o.getClass().equals(clazz)) {
                    // 将对应的元素进行类型转换
                    result.add(clazz.cast(o));
                }
            }
            return result;
        }
        return result;
    }

    /**
     * 获取对象的setter方法。
     *
     * @param obj 对象
     * @return 对象的setter方法列表
     */
    public static List<Method> getSetterMethods(Object obj)
    {
        // setter方法列表
        List<Method> setterMethods = new ArrayList<Method>();

        // 获取所有方法
        Method[] methods = obj.getClass().getMethods();

        // 查找setter方法

        for (Method method : methods)
        {
            Matcher m = SET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 1))
            {
                setterMethods.add(method);
            }
        }
        // 返回setter方法列表
        return setterMethods;
    }

    /**
     * 获取对象的getter方法。
     *
     * @param obj 对象
     * @return 对象的getter方法列表
     */

    public static List<Method> getGetterMethods(Object obj)
    {
        // getter方法列表
        List<Method> getterMethods = new ArrayList<Method>();
        // 获取所有方法
        Method[] methods = obj.getClass().getMethods();
        // 查找getter方法
        for (Method method : methods)
        {
            Matcher m = GET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 0))
            {
                getterMethods.add(method);
            }
        }
        // 返回getter方法列表
        return getterMethods;
    }

    /**
     * 检查Bean方法名中的属性名是否相等。<br>
     * 如getName()和setName()属性名一样，getName()和setAge()属性名不一样。
     *
     * @param m1 方法名1
     * @param m2 方法名2
     * @return 属性名一样返回true，否则返回false
     */

    public static boolean isMethodPropEquals(String m1, String m2)
    {
        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
    }

    /**
     * 去掉集合中属性相同的元素
     * @param keyExtractor
     * @param <T>
     * @return
     */
    public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
        Map<Object, Boolean> seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }

    /**
     * 对象转String 数组
     */

    public static String[] ObjectToStringArr(Object obj){

        String[] str ={};

        if(ObjectUtils.isEmpty(obj)){
            return str;
        }

        try{
            //通过getDeclaredFields()方法获取对象类中的所有属性（含私有）
            Field[] fields = obj.getClass().getDeclaredFields();
            int j = fields.length;
            str = new String[fields.length+1];
            for (int i = 0; i < fields.length; i++) {
                //设置允许通过反射访问私有变量
                fields[i].setAccessible(true);
                //获取字段的值
                String value = "";
                if(ObjectUtils.isNotEmpty(fields[i].get(obj))){
                    value = fields[i].get(obj).toString();
                }
                //获取字段属性名称
                String name = fields[i].getName();




                //其他自定义操作
                if(name.equalsIgnoreCase("effectiveDate") || name.equalsIgnoreCase("expiryDate") ){
                    value = DateUtils.geLinToDate(value);
                }
                if(name.equalsIgnoreCase("premiumReceivedDate")){
                    value = new SimpleDateFormat("yyyy-MM-dd").format(value);
                    str[i] = value;
                }
                if(!name.equalsIgnoreCase("planMethod")&&!name.equalsIgnoreCase("id")&&!name.equalsIgnoreCase("serialVersionUID") && !name.equalsIgnoreCase("oldPlanRate") && !name.equalsIgnoreCase("sn")){
                    str[i] = value;
                }



            }
        }
        catch (Exception ex){
            //处理异常
        }
        return str;
    }

    /**
     * 删除数组中为null的元素
     */

    public static String[] removeString(String[] strings){
        //String[] array = {"I", null, "love", null, "Java" };
        List<String> values = new ArrayList<String>();
        for(String data: strings) {
            if(data != null) {
                values.add(data);
            }
        }
        String[] target = values.toArray(new String[values.size()]);
        return target;
    }
    public static <T> String getChangedFields(T newBean, T oldBean){
        Field[] fields = newBean.getClass().getDeclaredFields();
        StringBuilder builder = new StringBuilder();
        for(Field field : fields) {
            field.setAccessible(true);
            if (field.isAnnotationPresent(ForUpdate.class)) {
                try {
                    Object newValue = field.get(newBean);
                    Object oldValue = field.get(oldBean);
                    if(!Objects.equals(newValue, oldValue)) {
                        builder.append(field.getAnnotation(ForUpdate.class).fieldName()); //获取字段名称
                        builder.append(": {更改前：");
                        builder.append(newValue);
                        builder.append(", 更改后：");
                        builder.append(oldValue);
                        builder.append("}\n");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return builder.toString();
    }


}
